﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using KC.Framework.Tenant;
using KC.Service.Account;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
using KC.DTO.Account;
using KC.Service.Core.Extension;
using KC.Service.Core;
using KC.Framework.Extension;
using KC.Framework.Base;

namespace KC.Web.Account.Controllers
{
    public class MenuController : AccountBaseController
    {
        private IRoleService RoleService => ServiceProvider.GetService<IRoleService>();
        private IMenuService MenuService => ServiceProvider.GetService<IMenuService>();
        public MenuController(
            Tenant tenant,
            IServiceProvider serviceProvider,
            ILogger<RoleController> logger)
            : base(tenant, serviceProvider, logger)
        {
        }

        [MVC.Core.Extension.MenuFilter("菜单权限管理", "菜单管理", "/Menu/Index",
        Version = TenantConstant.DefaultVersion, TenantType = TenantConstant.DefaultTenantType, SmallIcon = "fa fa-sitemap", AuthorityId = "08D986E5-CB98-4F2B-B08A-040B4C935224",
        DefaultRoleId = RoleConstants.AdminRoleId, Order = 1, IsExtPage = false, Level = 3)]
        [MVC.Core.Extension.PermissionFilter("菜单管理", "菜单管理", "/Menu/Index", "08D986E5-CB98-4F2B-B08A-040B4C935224",
            DefaultRoleId = RoleConstants.AdminRoleId, Order = 1, IsPage = true, ResultType = ResultType.ActionResult)]
        public ActionResult Index()
        {
            return View();
        }

        #region 菜单管理

        public async Task<JsonResult> LoadMenuList(string searchValue)
        {
            List<MenuNodeSimpleDTO> node = new List<MenuNodeSimpleDTO>();
            List<MenuNodeSimpleDTO> childrenNodes = new List<MenuNodeSimpleDTO>();

            if (IsSystemAdmin)
            {
                var result = await MenuService.GetRootMenusByNameAsync(searchValue);
                return Json(result.MapTo<KC.DTO.Core.TreeSimpleDTO>());
            }
            Func<MenuNodeSimpleDTO, bool> predict = m => true;
            if (!string.IsNullOrWhiteSpace(searchValue))
            {
                predict = m => (m.text.Contains(searchValue));
            }

            var menuTress = await GetCurrentUserMenuTree(predict);
            if (string.IsNullOrEmpty(searchValue))
                return Json(menuTress.MapTo<KC.DTO.Core.TreeSimpleDTO>());
            else
                return Json(PrepareTreeSimpleDTO(menuTress, ref node, ref childrenNodes, searchValue));
        }
        public async Task<JsonResult> LoadMenuTree()
        {
            var tree = await MenuService.GeAllSimpleMenuTreesAsync();

            var rootMenu = new MenuNodeSimpleDTO() { text = "顶级菜单", children = tree };
            return Json(new List<MenuNodeSimpleDTO> { rootMenu });
        }

        public PartialViewResult GetMenuForm(int id = 0)
        {
            var model = id != 0 ? MenuService.GetMenuById(id) : new MenuNodeDTO();
            var dropItems = GetDropDownItemsByEnum(new List<TenantVersion>()
            {
                TenantVersion.None,
                TenantVersion.Customized
            });
            ViewBag.SystemVersionList = dropItems;
            ViewBag.SelectedVersionIds = dropItems.Select(m => int.Parse(m.Value))
                .Where(m => (model.Version & (TenantVersion)m) != 0)
                .ToCommaSeparatedInt();

            int? selectValue = null;
            if (id != 0 && model.TenantType.HasValue)
                selectValue = (int)model.TenantType;
            ViewBag.TenantTypeList = GetDropDownItemsByEnumWithAll<TenantType>(
                selectValue);
            ViewBag.SelectedTenantType = selectValue;
            return PartialView("_menuForm", model);
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        [MVC.Core.Extension.PermissionFilter("菜单管理", "保存菜单数据", "/Menu/SaveMenu", "9DFC51A6-E5F9-480C-BB99-D619F9E5E690",
            DefaultRoleId = RoleConstants.AdminRoleId, Order = 2, IsPage = false, ResultType = ResultType.JsonResult)]
        public JsonResult SaveMenu(MenuNodeDTO model)
        {
            if (model.ParentId == 0)
                model.ParentId = null;
            //model.ApplicationId = CurrentOperationApplicationId;
            ModelState.Remove("IsDeleted");
            ModelState.Remove("CreatedDate");
            ModelState.Remove("ModifiedDate");
            if (!ModelState.IsValid)
                return base.ThrowErrorJsonMessage(false, "数据有误，请详查!");

            return GetServiceJsonResult(() =>
            {
                model.Level = model.ParentId > 0 ? 2 : 1;
                if (model.ParentId.HasValue && model.ParentId > 0)
                {
                    var parentMenu = MenuService.GetMenuById(model.ParentId.Value);
                    if (null == parentMenu)
                    {
                        throw new ArgumentException(string.Format("父级ID:{0} 未找到！", model.ParentId));
                    }
                    if (parentMenu.Level >= 2)
                    {
                        throw new ArgumentException(string.Format("父级ID:{0} 不能作为父级！", model.ParentId));
                    }
                    if (model.id == model.ParentId)
                    {
                        throw new ArgumentException(string.Format("父级ID:{0} 不能作为父级！", model.ParentId));
                    }
                }

                var result = MenuService.SaveMenu(model, CurrentUserId, CurrentUserDisplayName);
                if (result)
                {
                    //清除该用户菜单缓存
                    var cacheKey = TenantName.ToLower() + "-CurrentUserMenus-" + CurrentUserId;
                    CacheUtil.RemoveCache(cacheKey);
                }
                return result;
            });
        }

        [MVC.Core.Extension.PermissionFilter("菜单管理", "删除菜单数据", "/Menu/RemoveMenu", "E3A5DD3D-A848-42DE-BE53-C46EE1D0D582",
            DefaultRoleId = RoleConstants.AdminRoleId, Order = 3, IsPage = false, ResultType = ResultType.JsonResult)]
        public JsonResult RemoveMenu(int id)
        {
            return GetServiceJsonResult(() =>
            {
                var menu = MenuService.GetMenuById(id);
                if (null == menu)
                {
                    throw new ArgumentException(string.Format("未找到菜单ID:{0}", id));
                }
                if (menu.children.Any())
                {
                    throw new ArgumentException(string.Format("菜单:【{0}】存在子菜单，无法删除，请先删除子菜单！", menu.text));
                }

                var result = MenuService.RemoveMenuById(id, CurrentUserId, CurrentUserDisplayName);
                if (result)
                {
                    //清除该用户菜单缓存
                    var cacheKey = TenantName.ToLower() + "-CurrentUserMenus-" + CurrentUserId;
                    CacheUtil.RemoveCache(cacheKey);
                }
                return result;
            });

        }

        private List<KC.DTO.Core.TreeSimpleDTO> PrepareTreeSimpleDTO(List<MenuNodeSimpleDTO> model, ref List<MenuNodeSimpleDTO> node, ref List<MenuNodeSimpleDTO> childrenNodes, string menuSearchKey)
        {
            model = model.OrderByDescending(m => m.children.Count()).ToList();
            foreach (var m in model)
            {
                if (m.children.Any())
                {
                    m.children.RemoveAll(o => !o.text.Contains(menuSearchKey));
                    childrenNodes.AddRange(m.children);
                    node.Add(m);
                }
                else if (childrenNodes.All(o => o.id != m.id))
                    node.Add(m);

                if (m.children.Any())
                {
                    PrepareTreeSimpleDTO(m.children, ref node, ref childrenNodes, menuSearchKey);
                }
            }
            return node.Distinct().MapTo<KC.DTO.Core.TreeSimpleDTO>();
        }
        #endregion

        #region 菜单角色管理
        [MVC.Core.Extension.MenuFilter("菜单权限管理", "菜单角色管理", "/Menu/RoleInMenu",
            Version = TenantConstant.DefaultVersion, TenantType = TenantConstant.DefaultTenantType, SmallIcon = "fa fa-sitemap", AuthorityId = "29FC3DD2-E8C7-4EA7-A5CC-AF7F57B106D9",
            DefaultRoleId = RoleConstants.AdminRoleId, Order = 2, IsExtPage = true, Level = 3)]
        [MVC.Core.Extension.PermissionFilter("菜单角色管理", "菜单角色管理", "/Menu/RoleInMenu", "29FC3DD2-E8C7-4EA7-A5CC-AF7F57B106D9",
            DefaultRoleId = RoleConstants.AdminRoleId, Order = 1, IsPage = true, ResultType = ResultType.ActionResult)]
        public ActionResult RoleInMenu(int id = 0)
        {
            ViewBag.menuId = id;
            ViewBag.canEditRole = base.IsSystemAdmin;
            return View("RoleInMenu");
        }

        public async Task<JsonResult> GetRoleInMenu(int id = 0)
        {
            //返回所有菜单所有角色选中角色
            var menu = MenuService.GetDetailMenuById(id);
            var role = await RoleService.GetAllSimpleRolesAsync();
            if (menu == null)
            {
                return Json(role);
            }
            var roleList = new List<RoleSimpleDTO>();

            if (menu.Role.Any())
            {
                var checkIds = menu.Role.Select(m => m.RoleId).ToList();
                roleList = GetCheckRoleList(checkIds, role);
            }
            else
            {
                roleList = role;
            }
            if (!IsSystemAdmin && roleList != null)
            {
                var list = new List<RoleSimpleDTO>();
                //查询当前登录用户具有哪些角色(不是系统管理员)  
                var rolesIdlist = CurrentUser.RoleIds;

                var datalist = roleList.Where(c => rolesIdlist.Contains(c.RoleId));
                //查询出自己创建的角色
                var datalist2 = roleList.Where(c => c.CreatedBy == CurrentUserId);
                list.AddRange(datalist);
                list.AddRange(datalist2);
                return Json(list);
            }

            return Json(roleList);
        }

        [MVC.Core.Extension.PermissionFilter("菜单角色管理", "保存菜单角色数据", "/Menu/SubmitRoleInMenu", "6862116B-CA67-44DA-9E6A-D5C05DA7F964",
            DefaultRoleId = RoleConstants.AdminRoleId, Order = 2, IsPage = false, ResultType = ResultType.JsonResult)]
        public JsonResult SubmitRoleInMenu(string userId, List<string> addList, string type, int menuId = 0)
        {
            return base.GetServiceJsonResult(() =>
            {
                if (addList == null)
                    addList = new List<string>();
                var add = new List<string>();
                if (addList.Any())
                    add.AddRange(addList.Distinct());
                var result = false;
                if (menuId == 0)
                    throw new ArgumentNullException("menuId", "选中的菜单Id为空");

                //修改菜单角色
                result = MenuService.UpdateRoleInMenu(menuId, add, CurrentUserId,
                    CurrentUserDisplayName);
                //分配角色成功，清除用户缓存，以便重新获取角色权限
                if (result)
                    ClearUserCacheByRoles(add);

                return result;
            });
        }
        #endregion
    }
}